﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;

namespace Surf.Thriftinvoker.Demo.Thrift.Transport
{
    /// <summary>服务端 Socket 通讯器</summary>
    public class TSocketServerTransport : TServerTransport
    {
        #region Fields
        private TcpListener _server = null;
        private int _port = 0;
        private int _clientTimeout = 0;
        private bool _useBufferedSockets = false;
        #endregion

        #region Ctor
        public TSocketServerTransport(TcpListener listener) : this(listener, 0) { }
        public TSocketServerTransport(TcpListener listener, int clientTimeout)
        {
            _server = listener;
            _clientTimeout = clientTimeout;
        }
        public TSocketServerTransport(int port) : this(port, 0) { }
        public TSocketServerTransport(int port, int clientTimeout)
            : this(port, clientTimeout, false) { }
        public TSocketServerTransport(int port, int clientTimeout, bool useBufferedSockets)
        {
            _port = port;
            _clientTimeout = clientTimeout;
            _useBufferedSockets = useBufferedSockets;
            try
            {
                // Make server socket
                _server = TSocket.CreateTcpListener(_port);
                _server.Server.NoDelay = true;
            }
            catch (Exception ex)
            {
                _server = null;
                throw new Exception("Could not create ServerSocket on port " + _port + ".", ex);
            }
        }
        #endregion
        public override void Listen()
        {
            if (_server != null)
            {
                try
                {
                    _server.Start();
                }
                catch (SocketException ex)
                {
                    throw new Exception("Could not accept on listening socket :" + ex.Message, ex);
                }
            }
        }

        public override void Close()
        {
            if (_server != null)
            {
                try
                {
                    _server.Stop();
                }
                catch (Exception ex)
                {
                    throw new Exception("WARNING: Could not close server socket: " + ex, ex);
                }
                _server = null;
            }
        }

        protected override TTransport AcceptImpl()
        {
            if (_server == null)
                throw new Exception("No underlying server socket.");

            try
            {
                TSocket socket = null;
                TcpClient tcpClient = _server.AcceptTcpClient();
                try
                {
                    socket = new TSocket(tcpClient);
                    socket.Timeout = _clientTimeout;
                    // Todo if UseBufferedSockets
                    return socket;
                }
                catch (Exception ex)
                {
                    if (socket != null)
                        socket.Dispose();
                    else
                        ((IDisposable)tcpClient).Dispose();
                    throw ex;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
